//
// Created by 33145 on 2023/6/9.
//
#include "../rocket/tcp/tcp_server.h"
#include "../rocket/common/rocket.h"
#include <memory>
#include <google/protobuf/service.h>

#include "../rocket/common/rocket.h"
#include "../rocket/tcp/tcp_client.h"
#include "order.pb.h"
#include "../rocket/rpc/rpc_dispatcher.h"
#include "../rocket/rpc/rpc_channel.h"
#include "../rocket/rpc/rpc_controller.h"
#include "../rocket/rpc/rpc_closure.h"

void test_tcp_client() {
  rocket::IPNetAddr::ptr addr = std::make_shared<rocket::IPNetAddr>("127.0.0.1", 12345);
  rocket::TCPClient::ptr client = std::make_shared<rocket::TCPClient>(addr);
  client->connect([addr, client]() {

    LOG_DEBUG("connect to [%s] success", addr->toString().c_str());
    rocket::TinyPBProtocol::ptr message = std::make_shared<rocket::TinyPBProtocol>();
    message->setReqId("99998888");

    std::shared_ptr<makeOrderRequest> request = std::make_shared<makeOrderRequest>();
    request->set_price(100);
    request->set_goods("apple");

    if (!request->SerializeToString(&(message->_pb_data))) {
      LOG_ERROR("serialize error");
    }

    message->_method_name = "Order.makeOrder";


    client->writeMessage(message, [request](rocket::AbstractProtocol::ptr msg_ptr) {
      auto msg = std::dynamic_pointer_cast<rocket::TinyPBProtocol>(msg_ptr);
      LOG_DEBUG("send message success : request: [%s]", request->ShortDebugString().c_str());
    });
    client->readMessage("99998888", [](rocket::AbstractProtocol::ptr msg_ptr) {
      auto msg = std::dynamic_pointer_cast<rocket::TinyPBProtocol>(msg_ptr);
      LOG_DEBUG("req_id : [%s] -- get response [%s]", msg->getReqId().c_str(), msg->_pb_data.c_str());

      makeOrderRequest response;
      if (!response.ParseFromString(msg->_pb_data)) {
        LOG_ERROR("response.ParseFromString error");
        return;
      }
      LOG_DEBUG("get response success, response [%s]", response.ShortDebugString().c_str());
    });
  });
}

void test_rpc_channel() {
  rocket::IPNetAddr::ptr addr = std::make_shared<rocket::IPNetAddr>("127.0.0.1", 12345);
  rocket::RPCChannel::ptr channel = std::make_shared<rocket::RPCChannel>(addr);
  // rocket::RPCChannel::ptr channel(new rocket::RPCChannel(addr));
  // 一个客户端的存根 存放.proto文件中的方法

  std::shared_ptr<makeOrderRequest> request = std::make_shared<makeOrderRequest>();
  request->set_price(100);
  request->set_goods("banana");
  std::shared_ptr<makeOrderResponse> response = std::make_shared<makeOrderResponse>();
  std::shared_ptr<rocket::RPCController> controller = std::make_shared<rocket::RPCController>();
  controller->SetMsgId("99998888");
  std::shared_ptr<rocket::RPCClosure> closure = std::make_shared<rocket::RPCClosure>([controller, request, response, channel]() mutable {
    if (controller->GetErrorCode() != 0) {
      LOG_ERROR("call rpc error, error code [%d], error info [%s]", controller->GetErrorCode(), controller->GetErrorInfo().c_str());

    } else {
      LOG_INFO("call rpc success, request[%s], response[%s]", request->ShortDebugString().c_str(), response->ShortDebugString().c_str());
      // 业务逻辑
    }
    LOG_INFO("now exit event loop");
    channel->getTCPClient()->stop();
    channel.reset();
  });

  channel->Init(controller, request, response, closure);

  // Order_Stub stub(channel.get());
  // stub.makeOrder(controller.get(), request.get(), response.get(), closure.get());

  controller->SetTimeout(5000); // 5s

  channel->CallMethod(Order::descriptor()->method(0), controller.get(), request.get(), response.get(), closure.get()) ;
}

int main() {
  rocket::Config::SetGlobalConfig("/home/orange/tinytiny-rpc/tinytinyRPC/conf/client.xml");
  rocket::Logger::InitGlobalLogger(0);

  // test_tcp_client();
  test_rpc_channel();
}